﻿using System;
using System.Collections.Generic;
using System.Text;

using System.Windows.Forms;
using BiaoQianPrint.Tools;
using BiaoQianPrint.YeWu;
using BiaoQianPrint.BaseData;
namespace BiaoQianPrint.Caculate
{
    //本程序的核心算法。
    //接收 3个文件。ShouHuo、BOM、YL ====》产生一个文件YL_new。
    class Ctrl_Create
    {
        string mSHFielPath ="";
        string mBomFilePath ="";
        string mYLFilePath = "";
        string mYLFileName_new = "";
        

        Ctrl_YLData objYL_New;
        Ctrl_YLData objYL_Old;
        Ctrl_Bom objBom;
        Ctrl_BiaoQianPrint objBiaoQian ;
        //开始计算
        //1、  收货表是“同DC”合并的。因此取出一个PN。
        public void DataDeal()
        {
            
            //首先判断是否合理。
            //若  YL文件的生成时间比 SH文件的时间完。那是不行的。
            mSHFielPath = Ctrl_MainData.getUserInfoInstance().getFilePath(FilePathType.SHFilePath);
            mBomFilePath = Ctrl_MainData.getUserInfoInstance().getFilePath(FilePathType.BOMFilePath);
            mYLFilePath = Ctrl_MainData.getUserInfoInstance().getFilePath(FilePathType.YLFilePath);
            //新余量文件的命名：
            mYLFileName_new = "YL_" + DateTime.Now.ToString("yyyyMMdd-hhmmss") + ".txt";

            Ctrl_SHData objSH = new Ctrl_SHData(mSHFielPath);
            objYL_New = new Ctrl_YLData(mYLFileName_new);
            objYL_Old = new Ctrl_YLData(mYLFilePath);
            objBom = new Ctrl_Bom(mBomFilePath);
            objBiaoQian = new Ctrl_BiaoQianPrint("BQ_" + DateTime.Now.ToString("yyyyMMdd-hhmmss") + ".txt", false);
            //前置条件，同SH日期的，同DC的，同PN的必须合并。
            //循环  收货表，对每个DC，执行相同的运算。
            foreach (Mdl_SHRow item in objSH.listData)
            {
               Mod_PN pn= DataDeal_OnePN(item);
               if (pn == null) break;

                //如果=0，表示 没有数据，都在余量里面了。不需要产生标签。
               if (pn.listDaDai.Count > 0)
               {
                   objBiaoQian.AddRow(pn);
               }
            }


            //先把未使用的余量表的数都加入到新余量里面。  使用的数，当时就给删除了。
            if (AddOldYLRowToNewYLData() == false)    //不出错的话，现在就全转入了。
            {
                MessageBox.Show("转入旧余量表数据出错！");
                return;
            }
            //然后把新余量表保存。
            objYL_New.SaveDataToFile();
            Ctrl_MainData.getUserInfoInstance().UpdateFilePath(FilePathType.YLFilePath, mYLFileName_new);
            //最后把标签保存大txt文件
            objBiaoQian.SaveDataToFile();
        }
        //2、针对这个PN，
        private Mod_PN DataDeal_OnePN(Mdl_SHRow itemSH)
        {
            Mod_PN pn = new Mod_PN();
            pn.mShouHuoDate = itemSH.SHDate;
            pn.mPN = itemSH.PN;
            //1、遍历  余量表， 找到和这个PN号相同的，数量。  二者数量之和。
            int mAllNum = itemSH.Num;

            Mdl_YLRow itemYL = getYLRowFromOldYLData(itemSH.PN);
            //如果找到了余量，那就记录下来。如果找不到，itemYL=null;
            if (itemYL != null)
            {
                mAllNum += itemYL.YLNum;
            }

            //2、用上面的mAllNum来计算外箱数量的余数。规则“不满一外箱的不发货，算下次计算的余数”

            //首先是遍历BOM，找到此PN号的BOM  
            int mNeiBom = 0, mZhongBom = 0, mWaiBom = 0;
            objBom.getBomNumByPN(itemSH.PN, out mNeiBom, out mZhongBom, out mWaiBom);
            if (mWaiBom == 0)
            {
                MessageBox.Show("PN号："+itemSH.PN+" 的外包装数量是0，不能继续计算，请更正BOM后再继续！");
                return null;
            }

            //接下来是计算  剩余的数量，先建立余量的对象。然后写入。  最后全部执行完成时，在把余量表写到txt中。
            int mYLNew_Num = mAllNum % mWaiBom;
            if (mYLNew_Num > 0)
            {
                Mdl_YLRow itemYL_new = new Mdl_YLRow();
                itemYL_new.PN = itemSH.PN;
                itemYL_new.DC = itemSH.DC;
                itemYL_new.YLNum = mYLNew_Num;
                objYL_New.addData(itemYL_new.PN,itemYL_new.DC,itemYL_new.YLNum,false);
            }
            
            //下面这个数就是：待装箱数量。  这个数可能是0  就是这次收货时，这个数字+余量数字，仍然不满一个外箱。
            int mCaculateNum = mAllNum - mYLNew_Num;
            if (mCaculateNum == 0) return pn;  //继续下一个吧，这个不用装箱了，也不打印标签了。而且上面刚刚把余量写入新余量表了。

            //3、开始装箱。待装数量>0情况，至少能装一个大箱。 

            //这个大箱的DC好判断。  有余量的就是混，否则就是不混的
            //大袋，就第一袋是混的，其它若有，都不是混的。
            int mDaDaiCount = mCaculateNum / mWaiBom;
            for (int i = 0; i < mDaDaiCount; i++)
            {
                Mod_DaDai objDaDai = new Mod_DaDai();
                objDaDai.BOM_WaiNum = mWaiBom;
                objDaDai.mDC = itemSH.DC;
                pn.listDaDai.Add(objDaDai);
            }
            if (itemYL != null)  pn.listDaDai[0].mDC = itemYL.DC + itemSH.DC;




            if (mZhongBom > 0)
            {
                pn.isHaveZhongDai = true;
                int mZhongDaiCount = mCaculateNum / mZhongBom;
                int mHunNo = getHunDaiSerialNo(itemYL, mZhongBom);
                for (int i = 1; i <= mZhongDaiCount; i++)
                {
                    Mod_ZhongDai objZhongDai = new Mod_ZhongDai();
                    objZhongDai.BOM_ZhongNum = mZhongBom;
                    if (i < mHunNo)
                        objZhongDai.mDC = itemYL.DC;
                    else if (i == mHunNo)
                        objZhongDai.mDC = itemYL.DC + itemSH.DC;
                    else if(i>mHunNo)
                        objZhongDai.mDC = itemSH.DC;

                    pn.listZhongDai.Add(objZhongDai);
                }
            }


            if (mNeiBom > 0)
            {
                pn.isHaveXiaoDai = true;
                int mXiaoDaiCount = mCaculateNum / mNeiBom;
                int mHunNo = getHunDaiSerialNo(itemYL, mNeiBom);
                for (int i = 1; i <= mXiaoDaiCount; i++)
                {
                    Mod_XiaoDai objXiaoDai = new Mod_XiaoDai();
                    objXiaoDai.BOM_XiaoNum = mNeiBom;

                    if (i < mHunNo)
                        objXiaoDai.mDC = itemYL.DC;
                    else if (i == mHunNo)
                        objXiaoDai.mDC = itemYL.DC + itemSH.DC;
                    else if (i > mHunNo)
                        objXiaoDai.mDC = itemSH.DC;

                    pn.listXiaoDai.Add(objXiaoDai);
                }
            }
            return pn;
            //计算完成了，是显示在  DataGridView里面。这个非常简单了。
               //然后是导出计算，也很简单。

            //还有就是，如何追踪，分析某个PN号的计算过程？　再说吧。做完这个就可以去安装测试了。
        }

        //返回的序号是从1开始的。
        //若不需要混箱。  返回0即可
        //若不足一袋，返回1.
        //若不足二袋，返回2
        private int getHunDaiSerialNo(Mdl_YLRow itemYL, int pBomNum)
        {
            if(itemYL==null) return 0;

            int pYLNum=itemYL.YLNum;
            if (pYLNum == 0) return 0;

            int result = 0;
            result = pYLNum / pBomNum;
            result++;
            return result;
        }

        //最多就找到一个。不可能出现多个。  规则“每次计算，每个PN号，只会留下一条记录！”
        //使用过就删除，为了最后把未使用的加入新余量表。
        private Mdl_YLRow getYLRowFromOldYLData(string pPN)
        {
            Mdl_YLRow resultItem = null;
            foreach (Mdl_YLRow obj in objYL_Old._listData)
            {
                if (obj.PN == pPN)
                {
                    resultItem = obj;
                    objYL_Old._listData.Remove(obj);//删除使用过的余量。
                    break;
                }
            }
            return resultItem;
        }

        //把旧余量表中未使用的row都加入新余量表
        private bool AddOldYLRowToNewYLData()
        {
            foreach (Mdl_YLRow obj in objYL_Old._listData)
            {
                objYL_New.addData(obj.PN, obj.DC, obj.YLNum, false);
            }
            return true;
        }
    }
}
